Lightkurve quicklook prototype¶
In [1]:
%matplotlib notebook
from lightkurve import KeplerTargetPixelFile
import numpy as np
Let’s make the Jupyter cells wider
In [2]:
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))
Download a Kepler target pixel file (TPF)¶
In [6]:
tpf = KeplerTargetPixelFile.from_archive('210698281', campaign=13)
In [7]:
xx=tpf.column + np.arange(tpf.shape[2])
yy=tpf.row + np.arange(tpf.shape[1])
x, y = np.meshgrid(xx, yy)
x_vals, y_vals = x[tpf.pipeline_mask], y[tpf.pipeline_mask]
x_vals, y_vals
Out[7]:
(array([491, 492, 489, 490, 491, 492, 493, 489, 490, 491, 492, 493, 491,
492, 493, 491, 492, 493]),
array([469, 469, 470, 470, 470, 470, 470, 471, 471, 471, 471, 471, 472,
472, 472, 473, 473, 473]))
Define a new interact routine including pixel selection for the mask¶
In [15]:
lc=tpf.to_lightcurve()
"""
Interact with a linked target pixel file and lightcurve
Parameters
----------
lc : an optional user-supplied pre-processed lightcurve for this target
Returns
-------
ax : matplotlib.axes._subplots.AxesSubplot
The matplotlib axes object.
"""
try:
from ipywidgets import interact
import ipywidgets as widgets
from bokeh.io import push_notebook, show, output_notebook
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import Span
from bokeh.models import LogColorMapper, CustomJS, Slider
from bokeh.layouts import row, column
from bokeh.themes import Theme
from bokeh.models.tools import HoverTool, PointDrawTool
from bokeh.models.widgets import Button
output_notebook()
except ImportError:
raise ImportError('The quicklook tool requires Bokeh and ipywidgets. See the Installation Guide.')
if lc is None:
lc = tpf.to_lightcurve()
source = ColumnDataSource(data=dict(
time=lc.time, flux=lc.flux,
cadence=lc.cadenceno,
quality=lc.quality))
source3 = ColumnDataSource(data=dict(tpf_flux=tpf.flux))
title = "Quicklook lightcurve for {} target {}".format(tpf.mission, tpf.keplerid)
p = figure(title=title, plot_height=300, plot_width=600, tools="tap,pan,wheel_zoom,box_zoom,reset")#, theme=theme)
p.yaxis.axis_label = 'Normalized Flux'
p.xaxis.axis_label = 'Time - 2454833 (days)'
p.step('time', 'flux', line_width=1, color='gray', source=source, nonselection_line_color='gray')
r = p.circle('time', 'flux', source=source, fill_alpha=0.3, size=8,line_color=None,
selection_color="firebrick", nonselection_fill_alpha=0.0,
nonselection_fill_color="grey",nonselection_line_color=None,
nonselection_line_alpha=0.0, fill_color=None,
hover_fill_color="firebrick",hover_alpha=0.9,hover_line_color="white")
p.add_tools(HoverTool(tooltips=[("index", "$index"),
("cadence", "@cadence"),
("time", "@time{0,0.000}"),
("flux", "@flux"),
("quality", "@quality")],
renderers=[r], mode='mouse', point_policy="snap_to_data"))
vert = Span(location=800, dimension='height', line_color='firebrick', line_width=4, line_alpha=0.5)
p.add_layout(vert)
s2 = figure(plot_width=300, plot_height=300, title='Target Pixel File', tools='tap, box_zoom, reset')
s2.yaxis.axis_label = 'Pixel Row Number'
s2.xaxis.axis_label = 'Pixel Column Number'
pedestal = np.nanmin(tpf.flux)
vlo, lo, med, hi, vhi = np.fix(np.nanpercentile(tpf.flux-pedestal, [0.2, 1, 50, 95, 99.8]))
color_mapper = LogColorMapper(palette="Viridis256", low=lo, high=hi)
s2_dat = s2.image([pedestal+tpf.flux[0,:,:]], x=tpf.column, y=tpf.row,
dw=tpf.shape[2], dh=tpf.shape[1], dilate=True,
color_mapper=color_mapper)
source2 = ColumnDataSource(data=dict(xx=x_vals+0.5, yy=y_vals+0.5))
r1 = s2.rect('xx', 'yy', 1, 1, source=source2, fill_color='gray', fill_alpha=0.4, line_color='white')
ptool = PointDrawTool(renderers=[r1])
s2.add_tools(ptool)
s2.toolbar.active_tap = ptool
def my_text_input_handler(attr, old, new):
print("X")
#uopdated label: " + new)
#ptool.on_change("value", my_text_input_handler)
#button = Button(label="Foo", button_type="success")
#def my_button_handler(new):
# print('Button option ' + str(new) + ' selected.')
#button.on_click(my_button_handler)
def update(f, v):
vert.update(location=tpf.time[f])
s2_dat.data_source.data['image'] = [tpf.flux[f,:,:]]
s2_dat.glyph.color_mapper.high = v[1]
s2_dat.glyph.color_mapper.low = v[0]
push_notebook()
callback = CustomJS(args=dict(source=source, source2=source2, source3=source3), code="""
var data = source3.data['tpf_flux'];
var lcurve = source.data['flux']
var f = cb_obj.value
for (var i = 0; i < lcurve.length; i++) {
lcurve[i] = lcurve[i] - f
}
source.change.emit();
""")
slider = Slider(start=0.1, end=4, value=1, step=.1, title="power")
slider.js_on_change('value', callback)
row1 = row(p, s2)
row_and_col = column(slider, row1)
show(row_and_col, notebook_handle=True)
n_cad, nx, ny = tpf.flux.shape
play = widgets.Play(
interval=10,
value=9,
min=0,
max=n_cad-1,
step=1,
description="Press play",
disabled=False)
wbutton = widgets.Button(
description='Click me',
disabled=False,
button_style='', # 'success', 'info', 'warning', 'danger' or ''
icon='check')
def on_button_clicked(b):
bool_mask = tpf.pipeline_mask*False
for xi, yi in zip(r1.data_source.data['xx'], r1.data_source.data['yy']):
xc = np.int(np.round(xi-0.5)-tpf.column)
yc = np.int(np.round(yi-0.5)-tpf.row)
bool_mask[xc, yc] = True
print(xi, yi, xc, yc)
source.data['flux'] = tpf.to_lightcurve(aperture_mask=bool_mask).flux
print('click', bool_mask.sum())
print('glyph', vars(r1.glyph))
print('data_source', vars(r1.data_source))
print('selected', vars(r1.data_source.selected))
wbutton.on_click(on_button_clicked)
f_slider = widgets.IntSlider(min=0,max=n_cad-1,step=1,value=5,
layout=widgets.Layout(width='40%', height='20px'))
vstep = np.round((hi-lo)/300.0, 1)
v_slider = widgets.FloatRangeSlider(value=[lo, hi],
min=0,
max=hi,
step=vstep,
description='v:',
continuous_update=False,
layout=widgets.Layout(width='30%', height='20px'))
widgets.jslink((play, 'value'), (f_slider, 'value'))
ui = widgets.HBox([play, f_slider, v_slider, wbutton])
out = widgets.interactive_output(update, {'f': f_slider, 'v':v_slider})
display(ui, out)
#return p
xx=tpf.column + np.arange(tpf.shape[2])
yy=tpf.row + np.arange(tpf.shape[1])
x, y = np.meshgrid(xx, yy)
x_vals, y_vals = x[tpf.pipeline_mask], y[tpf.pipeline_mask]
x_vals = x_vals[1:2]
y_vals = y_vals[1:2]
print(x_vals)
print(y_vals)
p
[492]
[469]
Out[15]:
Figure(
id = '3a9f33c6-b3c7-45a7-973a-b1d4d9faf80a', …)
Hmmm… it’s not working!